﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Web.Mvc;
using Savvy.TestExtensions; //For AssertExtentions.AssertThrows()

namespace MVCHelperExtensions.Test
{

  /// <summary>
  ///This is a test class for HTMLHelperExtensionsTest and is intended
  ///to contain all HTMLHelperExtensionsTest Unit Tests
  ///</summary>
  [TestClass()]
  public class HTMLHelperExtensionsTest
  {

	#region Details Tests
	#region Tests for default identifying properties
	[TestMethod()]
	public void LinkTo_should_return_valid_link_to_details_view_for_the_instance_given_a_model_insance_with_defaults_only_no_attributes()
	{
	  var modelInstance = new TestModel() { ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModels/Details/1"">linktext</a>",
		htmlHelper.LinkTo("linktext", modelInstance)
		);
	}

	[TestMethod()]
	public void LinkTo_should_return_valid_link_to_details_view_for_the_instance_given_model_instance_with_Id_property()
	{
	  var modelInstance = new TestModelWithId() { Id = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWithIds/Details/1"">linktext</a>",
		htmlHelper.LinkTo("linktext", modelInstance)
		);
	}

	[TestMethod()]
	public void LinkTo_should_return_valid_link_to_details_view_for_a_model_instance_with_id_property()
	{
	  var modelInstance = new TestModelWithid() { id = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWithids/Details/1"">linktext</a>",
		htmlHelper.LinkTo("linktext", modelInstance)
		);
	}

	[TestMethod()]
	public void LinkTo_should_return_valid_link_to_details_view_for_a_given_model_instance_with__ID_property()
	{
	  var modelInstance = new TestModelWith_ID() { _ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWith_IDs/Details/1"">linktext</a>",
		htmlHelper.LinkTo("linktext", modelInstance)
		);
	}

	[TestMethod()]
	public void LinkTo_should_return_valid_link_to_details_view_for_a_given_model_instance_with__Id_property()
	{
	  var modelInstance = new TestModelWith_Id() { _Id = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWith_Ids/Details/1"">linktext</a>",
		htmlHelper.LinkTo("linktext", modelInstance)
		);
	}

	[TestMethod()]
	public void LinkTo_should_return_valid_link_to_details_view_for_a_given_model_instance_with__id_property()
	{
	  var modelInstance = new TestModelWith_id() { _id = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWith_ids/Details/1"">linktext</a>",
		htmlHelper.LinkTo("linktext", modelInstance)
		);
	}
	#endregion

	[TestMethod()]
	public void LinkTo_should_return_valid_link_to_details_view_for_a_given_model_instance_where_the_AlternateID_property_is_decorated_with_HTMLHelperIdentifier_attribute()
	{
	  var modelInstance = new TestModelWithAlternateID() { AlternateID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWithAlternateIDs/Details/1"">linktext</a>",
		htmlHelper.LinkTo("linktext", modelInstance)
		);
	}

	[TestMethod()]
	public void LinkTo_should_throw_exception_if_model_has_no_identifying_property()
	{
	  var modelInstance = new TestModelWithoutID();
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  AssertExtensions.AssertThrows(
		typeof(NonInferrableModelIdException),
		() => { htmlHelper.LinkTo("linktext", modelInstance); }
	  );
	}

	[TestMethod()]
	public void LinkTo_should_get_controller_name_from_class_attribute()
	{
	  var modelInstance = new TestModelWithControllerName_OtherController() { ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/OtherController/Details/1"">linktext</a>",
		htmlHelper.LinkTo("linktext", modelInstance)
		);
	}

	[TestMethod()]
	public void LinkTo_should_return_valid_link_when_passed_a_class_with_HTMLHelperDetailsMethodName_attribute()
	{
	  var modelInstance = new TestModelWithDetailsMethodName_OtherDetails() { ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWithDetailsMethodName_OtherDetails/OtherDetails/1"">linktext</a>",
		htmlHelper.LinkTo("linktext", modelInstance)
		);
	}

	[TestMethod()]
	public void LinkTo_should_return_valid_link_with_route_values()
	{
	  var modelInstance = new TestModel() { ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModels/Details/1?urlparam=test"">linktext</a>",
		htmlHelper.LinkTo("linktext", modelInstance, new { urlparam = "test" })
		);
	}

	[TestMethod()]
	public void LinkTo_should_return_valid_link_with_html_attributes()
	{
	  var modelInstance = new TestModel() { ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a class=""test"" href=""/TEST_APP_MODIFIER/app/TestModels/Details/1"">linktext</a>",
		htmlHelper.LinkTo("linktext", modelInstance, null, new { @class = "test" })
		);
	}

	#region Make sure LinkToDetails is working tests
	[TestMethod()]
	public void LinkToDetails_should_return_valid_link()
	{
	  var modelInstance = new TestModel() { ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModels/Details/1"">linktext</a>",
		htmlHelper.LinkToDetails("linktext", modelInstance)
		);
	}
	[TestMethod()]
	public void LinkToDetails_should_return_valid_link_with_route_values()
	{
	  var modelInstance = new TestModel() { ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModels/Details/1?urlparam=test"">linktext</a>",
		htmlHelper.LinkToDetails("linktext", modelInstance, new { urlparam = "test" })
		);
	}

	[TestMethod()]
	public void LinkToDetails_should_return_valid_link_with_html_attributes()
	{
	  var modelInstance = new TestModel() { ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a class=""test"" href=""/TEST_APP_MODIFIER/app/TestModels/Details/1"">linktext</a>",
		htmlHelper.LinkToDetails("linktext", modelInstance, null, new { @class = "test" })
		);
	}
	#endregion
	#endregion

	#region Index Tests

	[TestMethod()]
	public void LinkToIndex_passed_a_class_type_should_return_link_to_index_method()
	{
	  var modelInstance = new TestModel();
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModels/Index"">linktext</a>",
		htmlHelper.LinkToIndex(typeof(TestModel), "linktext")
		);
	}

	[TestMethod()]
	public void LinkToIndex_should_returns_a_valid_link_using_a_class_with_an_alternate_index_method_name()
	{
	  var modelInstance = new TestModelWithIndexMethodName_OtherIndex();
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWithIndexMethodName_OtherIndices/OtherIndex"">linktext</a>",
		htmlHelper.LinkToIndex(typeof(TestModelWithIndexMethodName_OtherIndex), "linktext")
		);
	}

	[TestMethod()]
	public void LinkToIndex_should_return_valid_link_when_passed_route_value_for_alternate_controller_name_and_additional_url_param()
	{
	  var modelInstance = new TestModel();
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModels/Index?urlparam=test"">linktext</a>",
		htmlHelper.LinkToIndex(
		  typeof(TestModel),
		  "linktext",
		  new { urlparam = "test" } // route values
		));
	}

	[TestMethod()]
	public void LinkToIndex_should_return_valid_link_when_passed_html_attributes()
	{
	  var modelInstance = new TestModel();
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a class=""test"" href=""/TEST_APP_MODIFIER/app/TestModels/Index"">linktext</a>",
		htmlHelper.LinkToIndex(
		  typeof(TestModel),
		  "linktext",
		  null, // route values
		  new { @class = "test" } //html attributes
		));
	}

	[TestMethod()]
	public void GenericLinkToIndex_should_return_valid_link_without_route_values_or_html_attributes()
	{
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWithIndexMethodName_OtherIndices/OtherIndex"">linktext</a>",
		htmlHelper.LinkToIndex<TestModelWithIndexMethodName_OtherIndex>("linktext")
		);
	}

	[TestMethod()]
	public void GenericLinkToIndex_should_return_valid_link_with_route_values_but_no_html_attributes()
	{
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWithIndexMethodName_OtherIndices/OtherIndex?urlparam=test"">linktext</a>",
		htmlHelper.LinkToIndex<TestModelWithIndexMethodName_OtherIndex>(
		  "linktext",
		  new { urlparam = "test" } // route values
		));
	}

	[TestMethod()]
	public void GenericLinkToIndex_should_return_valid_link_with_route_values_and_html_attributes()
	{
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a class=""test"" href=""/TEST_APP_MODIFIER/app/TestModelWithIndexMethodName_OtherIndices/OtherIndex?urlparam=test"">linktext</a>",
		htmlHelper.LinkToIndex<TestModelWithIndexMethodName_OtherIndex>(
		  "linktext",
		  new { urlparam = "test" }, // route values
		  new { @class = "test" } // html attributes
		));
	}
	#endregion

	#region Edit Tests
	[TestMethod()]
	public void LinkToEdit_should_return_valid_link_when_passed_a_model_instance_without_decoration_attributes()
	{
	  var modelInstance = new TestModel() { ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModels/Edit/1"">linktext</a>",
		htmlHelper.LinkToEdit("linktext", modelInstance)
		);
	}

	[TestMethod()]
	public void LinkToEdit_should_return_valid_link_when_passed_a_model_instance_with_alternative_edit_action_name_attribute()
	{
	  var modelInstance = new TestModelWithEditMethodName_OtherEdit() { ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWithEditMethodName_OtherEdits/OtherEdit/1"">linktext</a>",
		htmlHelper.LinkToEdit("linktext", modelInstance)
		);
	}

	[TestMethod()]
	public void LinkToEdit_should_return_valid_link_with_route_values()
	{
	  var modelInstance = new TestModel() { ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModels/Edit/1?urlparam=test"">linktext</a>",
		htmlHelper.LinkToEdit(
		  "linktext",
		  modelInstance,
		  new { urlparam = "test" } // route values
		));
	}

	[TestMethod()]
	public void LinkToEdit_should_return_valid_link_with_html_attributes()
	{
	  var modelInstance = new TestModel() { ID = 1 };
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a class=""test"" href=""/TEST_APP_MODIFIER/app/TestModels/Edit/1"">linktext</a>",
		htmlHelper.LinkToEdit(
		  "linktext",
		  modelInstance,
		  null, // route values
		  new { @class = "test" } // HTML attributes
		));
	}
	#endregion

	#region New Tests
	[TestMethod()]
	public void LinkToNew_passed_a_class_type_should_return_a_valid_link()
	{
	  var modelInstance = new TestModel();
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModels/Create"">linktext</a>",
		htmlHelper.LinkToNew(typeof(TestModel), "linktext")
		);
	}

	[TestMethod()]
	public void LinkToNew_should_returns_a_valid_link_using_a_class_with_an_alternate_New_method_name()
	{
	  var modelInstance = new TestModelWithNewMethodName_OtherNew();
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWithNewMethodName_OtherNews/OtherNew"">linktext</a>",
		htmlHelper.LinkToNew(typeof(TestModelWithNewMethodName_OtherNew), "linktext")
		);
	}

	[TestMethod()]
	public void LinkToNew_should_return_valid_link_when_passed_route_value_for_alternate_controller_name_and_additional_url_param()
	{
	  var modelInstance = new TestModel();
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModels/Create?urlparam=test"">linktext</a>",
		htmlHelper.LinkToNew(
		  typeof(TestModel),
		  "linktext",
		  new { urlparam = "test" } // route values
		));
	}

	[TestMethod()]
	public void LinkToNew_should_return_valid_link_when_passed_html_attributes()
	{
	  var modelInstance = new TestModel();
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a class=""test"" href=""/TEST_APP_MODIFIER/app/TestModels/Create"">linktext</a>",
		htmlHelper.LinkToNew(
		  typeof(TestModel),
		  "linktext",
		  null, // route values
		  new { @class = "test" } //html attributes
		));
	}

	[TestMethod()]
	public void GenericLinkToNew_should_return_valid_link_without_route_values_or_html_attributes()
	{
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWithNewMethodName_OtherNews/OtherNew"">linktext</a>",
		htmlHelper.LinkToNew<TestModelWithNewMethodName_OtherNew>("linktext")
		);
	}

	[TestMethod()]
	public void GenericLinkToNew_should_return_valid_link_with_route_values_but_no_html_attributes()
	{
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a href=""/TEST_APP_MODIFIER/app/TestModelWithNewMethodName_OtherNews/OtherNew?urlparam=test"">linktext</a>",
		htmlHelper.LinkToNew<TestModelWithNewMethodName_OtherNew>(
		  "linktext",
		  new { urlparam = "test" } // route values
		));
	}

	[TestMethod()]
	public void GenericLinkToNew_should_return_valid_link_with_route_values_and_html_attributes()
	{
	  HtmlHelper htmlHelper = TestHelpers.GetHtmlHelperWithDefaultHttpContext();

	  Assert.AreEqual(
		@"<a class=""test"" href=""/TEST_APP_MODIFIER/app/TestModelWithNewMethodName_OtherNews/OtherNew?urlparam=test"">linktext</a>",
		htmlHelper.LinkToNew<TestModelWithNewMethodName_OtherNew>(
		  "linktext",
		  new { urlparam = "test" }, // route values
		  new { @class = "test" } // html attributes
		));
	}

	#endregion
  }
}
